package com.mpgame.utils;

import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import org.springframework.stereotype.Component;
import com.mpgame.database.redis.model.UserTokenInfo;
import com.mpgame.database.redis.utils.PlayerOnlineUtil;
import com.mpgame.database.redis.utils.RedisUtil;
import com.mpgame.common.utils.Log;

import javax.crypto.SecretKey;
import java.util.Date;
import java.util.Map;

@Component
public class JwtUtil {
    private static final String SECRET_KEY = "mpgame-secret-key-for-jwt-token-generation-2024";
    private static final int TOKEN_EXPIRATION = 24 * 60 * 60 * 1000; // 24小时
    private static final SecretKey key = Keys.hmacShaKeyFor(SECRET_KEY.getBytes());

    public String generateToken(UserTokenInfo userInfo) {
        try {
            return Jwts.builder()
                .setSubject(String.valueOf(userInfo.getAccountId()))
                .claim("username", userInfo.getUsername())
                .claim("nickname", userInfo.getNickname())
                .claim("accountId", userInfo.getAccountId())
                .claim("loginTime", userInfo.getLastLoginTimestamp())
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + TOKEN_EXPIRATION))
                .signWith(key, SignatureAlgorithm.HS256)
                .compact();
        } catch (Exception e) {
            Log.err("JWT Token生成失败：" + e.getMessage());
            return null;
        }
    }

    public boolean validateToken(String token) {
        try {
            Claims claims = Jwts.parserBuilder()
                .setSigningKey(key)
                .build()
                .parseClaimsJws(token)
                .getBody();


            // 检查登录时间是否是最新的
            Long loginTime = claims.get("loginTime", Long.class);
            if (loginTime != null) {
                Integer accountId = claims.get("accountId", Integer.class);
                if (accountId != null) {
                    // 从Redis获取最新的登录时间进行比较
                    UserTokenInfo userTokenInfo = PlayerOnlineUtil.getUserTokenInfoFromAccountId(accountId);
                    if(userTokenInfo != null){
                        Long latestLoginTs = userTokenInfo.getLastLoginTimestamp();
                        if(loginTime < latestLoginTs){
                            Log.warn("JWT Token已过期，用户重新登录过 (Token登录时间: " + loginTime + ", 最新登录时间: " + latestLoginTs + ")");
                            return false;
                        }
                    }
                }
            }
            return true;
        } catch (JwtException | IllegalArgumentException e) {
            Log.warn("JWT Token验证失败：" + e.getMessage());
            return false;
        }
    }

    public int getAccountIdFromToken(String token) {
        try {
            Claims claims = Jwts.parserBuilder()
                .setSigningKey(key)
                .build()
                .parseClaimsJws(token)
                .getBody();
            return claims.get("accountId", Integer.class);
        } catch (Exception e) {
            Log.err("从JWT Token获取AccountId失败：" + e.getMessage());
            return -1;
        }
    }

    public String getUsernameFromToken(String token) {
        try {
            Claims claims = Jwts.parserBuilder()
                .setSigningKey(key)
                .build()
                .parseClaimsJws(token)
                .getBody();
            return claims.get("username", String.class);
        } catch (Exception e) {
            Log.err("从JWT Token获取Username失败：" + e.getMessage());
            return null;
        }
    }
    /**
     * 获取Token中的登录时间戳
     */
    public Long getLoginTimeFromToken(String token) {
        try {
            Claims claims = Jwts.parserBuilder()
                .setSigningKey(key)
                .build()
                .parseClaimsJws(token)
                .getBody();
            return claims.get("loginTime", Long.class);
        } catch (Exception e) {
            Log.err("从JWT Token获取登录时间失败：" + e.getMessage());
            return null;
        }
    }
}
